#pragma once

#include<iostream>
#include <memory>
#include <cassert>
#include <fstream>
#include<string>
#include "utils.hpp"
#include "gbl_sym_table.hpp"
#include <vector>
#include <stack>

static GlobalSymbolTable global_symbol_table(0,nullptr), shadow_global_symbol_table(0,nullptr);
static FuncMetaTable func_meta_table, shadow_func_meta_table;

static int block_deep=0,shadow_block_deep;

// 标记上一条指令是否是同块的return指令
static bool bLastIsReturn=false, shadow_bLastIsReturn;
// 标记上一条指令是否是同块的break指令
static bool bLastIsBreak=false, shadow_bLastIsBreak;
// 标记上一条指令是否是同块的continue指令
static bool bLastIsContinue=false, shadow_bLastIsContinue;

static int if_def_count=0, shadow_if_def_count; 
static int while_def_count=0, shadow_while_def_count;

// 用于return之后的代码丢弃
static int current_block_num=0, shadow_current_block_num;
static int last_ret_block_num=-1, shadow_last_ret_block_num;

// 存储嵌套while的num
static std::stack<int> while_num_stack, shadow_while_num_stack;

// 存储当前函数名
static std::string current_in_fun_name, shadow_current_in_fun_name;

// 统计当前块指令数
static int current_cmd_count=0, shadow_current_cmd_count;

// 统计当前调用函数中的最大参数个数
static int max_called_func_params_num=0, shadow_max_called_func_params_num;

// 当前已分配的临时符号数
static int t_symb_cnt=0, shadow_t_symb_cnt;
// 数组指针已分配的临时符号数
static int t_arr_cnt=0, shadow_t_arr_cnt;
// 存放数组的元素集
static std::vector<std::string> gb_arr_elems, shawdow_gb_arr_elems;
// 存放数组大小
static std::vector<std::string> arr_dim_sizes, shadow_arr_dim_sizes;
// 存放数组深度大小
static int current_arr_deep=0, shadow_current_arr_deep;
// 存放数组内容填充的偏移
static int arr_fill_offset=0,shadow_arr_fill_offset;
// 存放数组内容的元素
static std::vector<std::string> arr_content_elems, shadow_arr_content_elems;

// 退出函数后，重置全局变量
static void reset_flag(){
  bLastIsReturn = bLastIsBreak = bLastIsContinue = false;
  last_ret_block_num = -1;
  block_deep=0;
  current_cmd_count=0;
  max_called_func_params_num=0;
}

static void temp_save_global(){
  // 排除max_called_func_params_num外, 数量应与全局变量一致
  global_symbol_table.temp_save();
  shadow_global_symbol_table=global_symbol_table;

  func_meta_table.temp_save();
  shadow_func_meta_table=func_meta_table;

  shadow_block_deep=block_deep;
  shadow_bLastIsReturn=bLastIsReturn;
  shadow_bLastIsBreak=bLastIsBreak;
  shadow_bLastIsContinue=bLastIsContinue;
  shadow_if_def_count=if_def_count;
  shadow_while_def_count=while_def_count;
  shadow_current_block_num=current_block_num;
  shadow_last_ret_block_num=last_ret_block_num;
  shadow_while_num_stack=while_num_stack;
  shadow_current_in_fun_name=current_in_fun_name;
  shadow_current_cmd_count=current_cmd_count;
  // shadow_max_called_func_params_num=max_called_func_params_num;
  shadow_t_symb_cnt=t_symb_cnt;
  shadow_t_arr_cnt=t_arr_cnt;
  shawdow_gb_arr_elems=gb_arr_elems;
  shadow_arr_dim_sizes=arr_dim_sizes;
  shadow_current_arr_deep=current_arr_deep;
  shadow_arr_fill_offset=arr_fill_offset;
  shadow_arr_content_elems=arr_content_elems;
}

static void recover_global(){
  // 排除max_called_func_params_num外, 数量应与全局变量一致
  global_symbol_table=shadow_global_symbol_table;
  global_symbol_table.recover();

  func_meta_table=shadow_func_meta_table;
  func_meta_table.recover();

  block_deep=shadow_block_deep;
  bLastIsReturn=shadow_bLastIsReturn;
  bLastIsBreak=shadow_bLastIsBreak;
  bLastIsContinue=shadow_bLastIsContinue;
  if_def_count=shadow_if_def_count;
  while_def_count=shadow_while_def_count;
  current_block_num=shadow_current_block_num;
  last_ret_block_num=shadow_last_ret_block_num;
  while_num_stack=shadow_while_num_stack;
  current_in_fun_name=shadow_current_in_fun_name;
  current_cmd_count=shadow_current_cmd_count;
  // max_called_func_params_num=shadow_max_called_func_params_num;
  t_symb_cnt=shadow_t_symb_cnt;
  t_arr_cnt=shadow_t_arr_cnt;
  gb_arr_elems=shawdow_gb_arr_elems;
  arr_dim_sizes=shadow_arr_dim_sizes;
  current_arr_deep=shadow_current_arr_deep;
  arr_fill_offset=shadow_arr_fill_offset;
  arr_content_elems=shadow_arr_content_elems;
}

static int get_a_symb_num(){
  return t_symb_cnt++;
}

class BaseAST {
 public:
  // virtual ~BaseAST() = default;

  std::string ident;
  bool isArr=false;

  virtual std::string Dump(std::string&) const = 0;
};

class BaseExpAST : public BaseAST {
public:
  const int exp_num; 
  std::unique_ptr<BaseAST> left_ast,right_ast,more_ast0;
  BaseExpAST(int _exp_num):exp_num(_exp_num){}
};

class LinkNodeAST {
 public:
  virtual ~LinkNodeAST() = default;
  std::unique_ptr<BaseAST> current;
  std::unique_ptr<LinkNodeAST> next;
};

class ExpLinkNodeAST {
 public:
  virtual ~ExpLinkNodeAST() = default;
  std::unique_ptr<BaseExpAST> current;
  std::unique_ptr<ExpLinkNodeAST> next;
};

class StrLinkNodeAST {
 public:
  virtual ~StrLinkNodeAST() = default;
  std::unique_ptr<std::string> current;
  std::unique_ptr<StrLinkNodeAST> next;
};

class ProgramRootAST : public BaseAST {
 public:
  std::unique_ptr<BaseAST> head_comp_unit;

  // 添加全局函数
  void add_gb_funcs(std::string &str) const {
    str+="decl @getint(): i32\n";
    func_meta_table.insert("getint","i32");

    str+="decl @getch(): i32\n";
    func_meta_table.insert("getch","i32");

    str+="decl @getarray(*i32): i32\n";
    func_meta_table.insert("getarray","i32");

    str+="decl @putint(i32)\n";
    func_meta_table.insert("putint","VOID");

    str+="decl @putch(i32)\n";
    func_meta_table.insert("putch","VOID");

    str+="decl @putarray(i32, *i32)\n";
    func_meta_table.insert("putarray","VOID");

    str+="decl @starttime()\n";
    func_meta_table.insert("starttime","VOID");

    str+="decl @stoptime()\n";
    func_meta_table.insert("stoptime","VOID");

    str+="\n\n";
  }

  // head -> CompUnitAST01 -> CompUnitAST02 -> ... -> CompUnitASTn
  std::string Dump(std::string &str) const override {
    add_gb_funcs(str);
    head_comp_unit->Dump(str);
    return "";
  }
};

class CompUnitAST : public BaseAST {
public:
  std::unique_ptr<BaseAST> func_def;
  // head -> CompUnitAST01 -> CompUnitAST02 -> ... -> CompUnitASTn
  CompUnitAST* next;

  std::string Dump(std::string &str) const override {
    const CompUnitAST* p=this;
    while(p!=nullptr){
      p->func_def->Dump(str);
      p = p->next;
      reset_flag();
    }
    return "";
  }
};

class FuncFParamAST : public BaseAST {
public:
  std::vector<std::unique_ptr<BaseAST>> dim_exps;
  int stype;
  std::string Dump(std::string &str) const override {
    return "";
  }
};

class FuncFParamsAST : public BaseAST {
public:
  std::vector<std::unique_ptr<FuncFParamAST>> params;
  std::string Dump(std::string &str) const override {

    return "";
  }
};

class FuncDefAST : public BaseAST {
 public:
  std::unique_ptr<std::string> func_type;
  std::unique_ptr<BaseAST> block;
  std::vector<std::unique_ptr<FuncFParamAST>> params;

  std::string Dump(std::string &str) const override {
    global_symbol_table.reset_and_clear_all();
    std::string s_params="";
    for(int i=0;i<params.size();i++){
      if(params[i]->isArr){
        std::vector<std::string> dim_sizes;
        for(int j=0;j<params[i]->dim_exps.size();j++){
          dim_sizes.push_back(params[i]->dim_exps[j]->Dump(str));
        }

        // 要清楚，第一维的数字数没有加入dim_exps的
        std::string arr_type="*i32";
        if(dim_sizes.size()>0){
          arr_type="[i32, "+dim_sizes[dim_sizes.size()-1]+"]";
          for(int j=dim_sizes.size()-2;j>=0;j--){
            arr_type="["+arr_type+", "+dim_sizes[j]+"]";
          }
          arr_type="*"+arr_type;
        }
        s_params+="@"+params[i]->ident+": "+arr_type;
      }
      else{
        s_params+="@"+params[i]->ident+": i32";
      }

      if(i != params.size()-1)s_params+=", ";
    }

    str+= "\nfun @"+ident+"("+s_params+")";
    current_in_fun_name=ident;
    func_meta_table.insert(ident,*func_type.get());

    // 写入参数类型
    if(*func_type.get()=="INT"){
      str += ": i32";
    }

    str+= " {\n";
    str+= "%entry:\n";

    // 先扫描，假写入
    temp_save_global();
    std::string fake_str;
    // 参数变量加入符号表
    for(int i=0;i<params.size();i++){
      std::string pr_name=params[i]->ident;
      if(params[i]->isArr){
        std::vector<std::string> dim_sizes;
        for(int j=0;j<params[i]->dim_exps.size();j++){
          dim_sizes.push_back(params[i]->dim_exps[j]->Dump(str));
        }
        std::string arr_type="*i32";
        if(dim_sizes.size()>0){
          arr_type="[i32, "+dim_sizes[dim_sizes.size()-1]+"]";
          for(int j=dim_sizes.size()-2;j>=0;j--){
            arr_type="["+arr_type+", "+dim_sizes[j]+"]";
          }
          arr_type="*"+arr_type;
        }

        fake_str+="\t%"+pr_name + " = alloc "+arr_type+"\n";
        global_symbol_table.insert_arr_ptr_info("%"+pr_name,params[i]->dim_exps.size()+1, block_deep);
      }
      else{
        fake_str+="\t%"+pr_name + " = alloc i32\n";
      }
      fake_str+="\tstore @"+pr_name + ", %"+pr_name+"\n";
      global_symbol_table.insert_new_param(pr_name);
    }
    block->Dump(fake_str);
    recover_global();

    // 为调用函数预留的存放参数位置
    for(int i=0;i<max_called_func_params_num;i++){
      if(!global_symbol_table.sym_is_alloc("param"+std::to_string(i),1)){
        str+="\t@param"+std::to_string(i)+"_1 = alloc i32\n";
        global_symbol_table.record_alloc_sym("param"+std::to_string(i),1);
      }
    }

    for(int i=0;i<params.size();i++){
      std::string pr_name=params[i]->ident;
      if(params[i]->isArr){
        std::vector<std::string> dim_sizes;
        for(int j=0;j<params[i]->dim_exps.size();j++){
          dim_sizes.push_back(params[i]->dim_exps[j]->Dump(str));
        }
        std::string arr_type="*i32";
        if(dim_sizes.size()>0){
          arr_type="[i32, "+dim_sizes[dim_sizes.size()-1]+"]";
          for(int j=dim_sizes.size()-2;j>=0;j--){
            arr_type="["+arr_type+", "+dim_sizes[j]+"]";
          }
          arr_type="*"+arr_type;
        }

        str+="\t%"+pr_name + " = alloc "+arr_type+"\n";
        // 第一维未被push，所以要手动多加1
        global_symbol_table.insert_arr_ptr_info("%"+pr_name,params[i]->dim_exps.size()+1, block_deep);
      }
      else{
        str+="\t%"+pr_name + " = alloc i32\n";
      }

      str+="\tstore @"+pr_name + ", %"+pr_name+"\n";
      // 参数变量加入符号表
      global_symbol_table.insert_new_param(pr_name);
    }

    block->Dump(str);

    if(*func_type.get()=="VOID"){
      str+="\tret\n";
    }
    str+= "}\n";
    return "";
  }
};

class BlockAST : public BaseAST {
 public:
  std::vector<std::unique_ptr<BaseAST>> stmts;

  std::string Dump(std::string &str) const override {
    block_deep++;
    for(int i=0;i<stmts.size();i++){
      stmts[i]->Dump(str);
    }
    block_deep--;
    global_symbol_table.break_link(block_deep);
    return "";
  }
};

class StmtAST : public BaseAST {
 public:
  std::unique_ptr<BaseAST> exp,lval;
  // 0 代表返回式， 1代表赋值式， 2代表空返回， 3代表Block， 
  // 4代表Exp， 5代表仅';'， 6代表if/else分支， 7代表while循环
  // 8代表break， 9代表continue
  int stype;

  std::string Dump(std::string &str) const override {
    if(current_block_num == last_ret_block_num){
      return "";
    }
    else last_ret_block_num=-1;

    current_cmd_count++;
    bLastIsReturn=bLastIsBreak=bLastIsContinue=false;

    int temp_current_block_num = current_block_num;
    switch (stype)
    {
    case 0:
    {
      std::string last_sym = exp->Dump(str);
      str += "\tret "+last_sym+"\n";
      bLastIsReturn = true;
      last_ret_block_num=current_block_num;
      break;
    }
    case 1:
    {
      std::string last_sym = exp->Dump(str);
      std::string lval_ref;
      if(lval->isArr){
        lval_ref=lval->Dump(str);
      }
      else{
        lval_ref = global_symbol_table.var_get_ref(lval->ident,block_deep);
      }
      str+= "\tstore "+last_sym+", "+lval_ref+"\n";
      break;
    }
    case 2:
      str+= "\tret\n";
      bLastIsReturn=true;
      break;
    case 3:
    {
      current_block_num++;
      std::string last_sym = exp->Dump(str);
      break;
    }
    case 4:
    {
      exp->Dump(str);
      break;
    }
    case 5:
      break;
    case 6:
    {
      std::string if_num = exp->Dump(str);
      break;
    }
    case 7:
    {
      current_block_num++;
      exp->Dump(str);
      break;
    }
    case 8:
    {
      exp->Dump(str);
      last_ret_block_num=current_block_num;
      bLastIsBreak=true;
      break;
    }
    case 9:
    {
      exp->Dump(str);
      last_ret_block_num=current_block_num;
      bLastIsContinue=true;
      break;
    }
    default:assert(false);
    }

    current_block_num=temp_current_block_num;

    return "";
  }
};

class EqExpAST : public BaseExpAST {
 public:
  EqExpAST(int _exp_num):BaseExpAST(_exp_num){}
  std::string op;

  std::string Dump(std::string &str) const override {
    if(exp_num==1){
      return left_ast->Dump(str);
    }
    else if(exp_num==2){
      std::string left_ret=left_ast->Dump(str);
      std::string right_ret=right_ast->Dump(str);

      if(isConst(left_ret) && isConst(right_ret)){
        int left_value=std::stoi(left_ret), right_value=std::stoi(right_ret);
        if(op=="==")return std::to_string(left_value==right_value);
        else if(op=="!=")return std::to_string(left_value!=right_value);
        else assert(false);
      }

      if(isVarSymb(left_ret)){
        std::string left_temp_sym="%"+std::to_string(get_a_symb_num());
        str+="\t"+left_temp_sym+" = load "+left_ret+"\n";
        left_ret=left_temp_sym;
      }

      if(isVarSymb(right_ret)){
        std::string right_temp_sym="%"+std::to_string(get_a_symb_num());
        str+="\t"+right_temp_sym+" = load "+left_ret+"\n";
        right_ret=right_temp_sym;
      }

      std::string current_sym="%"+std::to_string(get_a_symb_num());
      if(op=="=="){
        str+= "\t"+current_sym + " = eq "+left_ret+", "+right_ret+"\n";
      }
      else if(op=="!="){
        str+= "\t"+current_sym + " = ne "+left_ret+", "+right_ret+"\n";
      }
      else{
        assert(false);
      }

      return current_sym;
    }
    else assert(false);

  }
};

class PrimaryExpAST : public BaseExpAST {
public:
  // std::string num;
  std::unique_ptr<BaseAST> lval;
  PrimaryExpAST(int _exp_num):BaseExpAST(_exp_num){}

  std::string Dump(std::string &str) const override {
    if(exp_num==-1){
      // 应该先判断是否为变量，再判断常量
      if(!global_symbol_table.isInConst(lval->ident, block_deep)) {
        if(lval->isArr){
          std::string lval_ptr=lval->Dump(str);
          if(global_symbol_table.contain_arr_dim_from(lval_ptr, block_deep)){
            // 如果只需要数组头指针
            int dims_num=global_symbol_table.get_arr_dim_info(lval_ptr,block_deep).size();

            std::string last_lval_ptr=lval_ptr;
            for(int i=0;i<dims_num;i++){
              std::string ptr_head_sym="%"+std::to_string(get_a_symb_num());
              str+="\t"+ptr_head_sym+" = getelemptr "+last_lval_ptr+", 0\n"; 
              last_lval_ptr=ptr_head_sym;
            }

            return last_lval_ptr;
          }

          if(lval_ptr.size()>12 && lval_ptr.substr(0,12)=="%undata_ptr_"){
            std::string ptr_head_sym="%"+std::to_string(get_a_symb_num());
            str+="\t"+ptr_head_sym+" = getelemptr "+lval_ptr+", 0\n"; 
            // 数组指针的话就直接返回指针就好
            return ptr_head_sym;
          }

          // 需要从地址中加载值
          std::string lval_value_sym="%"+std::to_string(get_a_symb_num());
          str+="\t"+lval_value_sym+" = load "+lval_ptr+"\n";
          return lval_value_sym;
        }
        else{
          std::string lval_name=lval->Dump(str);
          if(global_symbol_table.contain_arr_dim_from(lval_name, block_deep)){
            // 如果是数组指针，则只需要头
            std::string last_lval_name=lval_name;

            std::string ptr_head_sym="%"+std::to_string(get_a_symb_num());
            str+="\t"+ptr_head_sym+" = getptr "+last_lval_name+", 0\n"; 

            std::string head_elem_sym="%"+std::to_string(get_a_symb_num());
            str+="\t"+head_elem_sym+" = getelemptr "+ptr_head_sym+", 0\n";\

            return head_elem_sym;
          }
          else{
            return lval_name;
          }
        }
      }
      else {
        if(lval->isArr){
          std::string lval_ptr=lval->Dump(str);
          std::string lval_value_sym="%"+std::to_string(get_a_symb_num());
          // 需要从地址中加载值
          str+="\t"+lval_value_sym+" = load "+lval_ptr+"\n";
          return lval_value_sym;
        }
        else{
          return std::to_string(global_symbol_table.const_get_value(lval->ident,block_deep));
        }
      }
    }
    else if(exp_num==0){
      return ident;
    }
    else if(exp_num==1){
      return left_ast->Dump(str);
    }
    else{
      assert(false);
    }
  }
};

class LValAST : public BaseAST {
public:
  std::vector<std::unique_ptr<BaseAST>> exps;
  int stype;
  std::string Dump(std::string &str) const override {
    switch (stype)
    {
    case 0:
    {
      std::string its_ref=global_symbol_table.var_get_ref(ident,block_deep);

      // 如果是数组，则只需要引用
      if(global_symbol_table.contain_arr_dim_from(its_ref,block_deep)){
        return its_ref;
      }

      std::string t_temp_sym="%"+std::to_string(get_a_symb_num());
      str+="\t"+t_temp_sym+" = load "+its_ref+"\n";
      return t_temp_sym;
    }
    case 1:
    {
      // b. 逐级索引
      std::string last_arr_sym=global_symbol_table.var_get_ref(ident,block_deep);
      bool is_arr_ptr=global_symbol_table.contain_arr_ptr_from(last_arr_sym,block_deep);
      
      // 基于索引维数判断是获取数组指针还是元素指针
      bool is_completed_data=false;
      if(is_arr_ptr){
        int arr_ptr_num_dim_num=global_symbol_table.get_arr_ptr_info("%"+ident,block_deep);
        if(exps.size()==arr_ptr_num_dim_num){
          is_completed_data=true;
        }
      }
      else{
        // 现在知道它是数组变量了
        std::vector<std::string> dims=global_symbol_table.get_arr_dim_info(global_symbol_table.var_get_ref(ident, block_deep),block_deep);
        if(dims.size()==exps.size()){
          is_completed_data=true;
        }
      }

      // 如果是数组指针的话, 需要先load读指针
      if(is_arr_ptr){
        std::string sub_arr_p="%ptr_"+std::to_string(t_arr_cnt++);
        str+="\t"+sub_arr_p+" = load "+last_arr_sym+"\n";
        last_arr_sym=sub_arr_p;

        for(int i=0;i<exps.size();i++){
          std::string dim_exp=exps[i]->Dump(str);
          std::string sub_arr_p;
          if(i==exps.size()-1 && !is_completed_data){
            sub_arr_p="%undata_ptr_"+std::to_string(t_arr_cnt++);
          }
          else{
            sub_arr_p="%ptr_"+std::to_string(t_arr_cnt++);
          }

          // 如果是数组指针的话, 第一次需要getptr读指针
          if(i==0){
            str+="\t"+sub_arr_p+" = getptr "+last_arr_sym+", "+dim_exp+"\n";
          }
          else{
            str+="\t"+sub_arr_p+" = getelemptr "+last_arr_sym+", "+dim_exp+"\n";
          }
          
          last_arr_sym=sub_arr_p;
        }
      }
      else {
        for(int i=0;i<exps.size();i++){
          std::string dim_exp=exps[i]->Dump(str);

          std::string sub_arr_p;
          if(i==exps.size()-1 && !is_completed_data){
            sub_arr_p="%undata_ptr_"+std::to_string(t_arr_cnt++);
          }
          else{
            sub_arr_p="%ptr_"+std::to_string(t_arr_cnt++);
          }

          // 如果是普通数组的话, 需要getelemptr读出元素
          str+="\t"+sub_arr_p+" = getelemptr "+last_arr_sym+", "+dim_exp+"\n";
          last_arr_sym=sub_arr_p;
        }
      }

      return last_arr_sym;
    }
    default:
      assert(false);
    }
  }
};

class UnaryExpAST : public BaseExpAST {
public:
  const char op; 
  std::string fun_name;
  std::vector<std::unique_ptr<BaseAST>> real_params;
  UnaryExpAST(int _exp_num, char _op):BaseExpAST(_exp_num),op(_op){}

  std::string Dump(std::string &str) const override {
    if(op=='f'){
      // 函数调用
      std::string s_real_params="";

      // 调用无参函数
      if(exp_num==0)
      {
        // just pass
      }
      else if(exp_num==-1){ 
        if(max_called_func_params_num<real_params.size()){
          max_called_func_params_num=real_params.size();
        }

        std::vector<std::string> ret_syms;
        for(int i=0;i<real_params.size();i++){
          std::string ret_sym=real_params[i]->Dump(str);
          ret_syms.push_back(ret_sym);
        }

        for(int i=0;i<real_params.size();i++){
          s_real_params+=ret_syms[i];
          if(i!=real_params.size()-1){
            s_real_params+=", ";
          }
        }
      }
      else assert(false);

      if(func_meta_table.get_type(fun_name)!="VOID")
      {
        std::string current_sym="%"+std::to_string(get_a_symb_num());
        str+="\t"+current_sym+" = call @"+fun_name+"("+s_real_params+")\n";
        return current_sym;
      }
      else{
        str+="\tcall @"+fun_name+"("+s_real_params+")\n";
        return "";
      } 
    }

    std::string left_ret=left_ast->Dump(str);

    if(isConst(left_ret) && op!='f'){
      int left_value=std::stoi(left_ret);
      if(op=='+')return std::to_string(left_value);
      else if(op=='-')return std::to_string(-left_value);
      else if(op=='!')return std::to_string(!left_value);
      else assert(false);
    }

    if(op=='+')return left_ret;

    std::string current_sym="%"+std::to_string(get_a_symb_num());
    switch (op)
    {
    case '-':
      str+="\t" + current_sym + " = sub 0, " + left_ret+"\n";
      break;
    case '!':
      str+="\t" + current_sym + " = eq " + left_ret + ", 0\n";
      break;
    case 'f':
      str+="\t"+current_sym+" = call @"+fun_name+"("+left_ret+")\n";
      break;
    default:
      assert(false);
    }
    return current_sym;
  }
};

class MulExpAST : public BaseExpAST {
 public:
  MulExpAST(int _exp_num):BaseExpAST(_exp_num){}

  char op;

  std::string Dump(std::string &str) const override {
    if(exp_num==1){
      return left_ast->Dump(str);
    }
    else if(exp_num==2){
      std::string left_ret = left_ast->Dump(str);
      std::string right_ret = right_ast->Dump(str);

      if(isConst( left_ret) && isConst(right_ret)){
        int left_value=std::stoi(left_ret), right_value=std::stoi(right_ret);
        if(op=='*')return std::to_string(left_value*right_value);
        else if(op=='/')return std::to_string(left_value/right_value);
        else if(op=='%')return std::to_string(left_value%right_value);
        else assert(false);
      }

      std::string t_symb="%"+std::to_string(get_a_symb_num());
      switch (op)
      {
      case '*':
        str+= "\t"+t_symb + " = mul "+left_ret + ", " +right_ret+"\n";
        break;
      case '/':
        str+= "\t"+t_symb + " = div "+left_ret + ", " +right_ret+"\n";
        break;
      case '%':
        str+= "\t"+t_symb + " = mod "+left_ret + ", " +right_ret+"\n";
        break;
      default:
        assert(false);
      }
      return t_symb;
    }
    else assert(false);
  }
};

class AddExpAST : public BaseExpAST {
 public:
  AddExpAST(int _exp_num):BaseExpAST(_exp_num){}

  char op;

  std::string Dump(std::string &str) const override {
    if(exp_num==1){
      return left_ast->Dump(str);
    }
    else if(exp_num==2){
      std::string left_ret = left_ast->Dump(str);
      std::string right_ret = right_ast->Dump(str);

      if(isConst(left_ret) && isConst(right_ret)){
        int left_value=std::stoi(left_ret), right_value=std::stoi(right_ret);
        if(op=='+')return std::to_string(left_value+right_value);
        else if(op=='-')return std::to_string(left_value-right_value);
        else assert(false);
      }

      std::string t_symb="%"+std::to_string(get_a_symb_num());
      if(op=='+'){
        str+= "\t"+t_symb + " = add "+left_ret + ", " +right_ret+"\n";
      }
      else if(op=='-'){
        str+= "\t"+t_symb + " = sub "+left_ret + ", " +right_ret+"\n";
      }
      else{
        assert(false);
      }
      return t_symb;
    }
    else {
      assert(false);
    }
  }
};

class RelExpAST : public BaseExpAST {
 public:
  RelExpAST(int _exp_num):BaseExpAST(_exp_num){}

  std::string op;

  std::string Dump(std::string &str) const override {
    if(exp_num==1){
      return left_ast->Dump(str);
    }
    else if(exp_num==2){
      std::string left_ret = left_ast->Dump(str);
      std::string right_ret = right_ast->Dump(str);

      if(isConst(left_ret) && isConst(right_ret)){
        int left_value=std::stoi(left_ret), right_value=std::stoi(right_ret);
        if(op=="<" && left_value<right_value)return "1";
        else if(op==">" && left_value>right_value)return "1";
        else if(op=="<=" && left_value<=right_value)return "1";
        else if(op==">=" && left_value>=right_value)return "1";
        else return "0";
      }

      std::string t_symb="%"+std::to_string(get_a_symb_num());
      if(op=="<"){
        str+= "\t"+t_symb + " = lt "+left_ret + ", " +right_ret+"\n";
        return t_symb;
      }
      else if(op==">"){
        str+= "\t"+t_symb + " = gt "+left_ret + ", " +right_ret+"\n";
        return t_symb;
      }
      else if(op=="<="){
        str+= "\t"+t_symb + " = le "+left_ret + ", " +right_ret+"\n";
        return t_symb;
      }
      else if(op==">="){
        str+= "\t"+t_symb + " = ge "+left_ret + ", " +right_ret+"\n";
        return t_symb;
      }
      else{
        assert(false);
      }
    }
    else assert(false);

  }
};

class LOrExpAST : public BaseExpAST {
 public:
  LOrExpAST(int _exp_num):BaseExpAST(_exp_num){}

  std::string Dump(std::string &str) const override {
    
    if(exp_num==1){
      return left_ast->Dump(str);
    }
    else if(exp_num==2){
      std::string left_ret = left_ast->Dump(str);
      std::string right_ret;
      bool right_ret_exec=false;

      if(isConst(left_ret)){
        if(left_ret!="0"){
          return "1";
        }
        else {
          right_ret = right_ast->Dump(str);
          right_ret_exec=true;
          if(isConst(right_ret)){
            if(right_ret!="0"){
              return "1";
            }
            else return "0";
          }
        }
      }

      std::string reduce_left_sym = "%"+std::to_string(get_a_symb_num());
      str+= "\t"+reduce_left_sym + " = ne "+left_ret + ", 0\n";

      // 短路
      int current_if_num=if_def_count++;
      std::string if_num=std::to_string(current_if_num);

      // 变量result_0，用于存储短路结果
      if(!global_symbol_table.sym_is_alloc("br_result",1)){
        str+="\t@br_result_1 = alloc i32\n";
        global_symbol_table.record_alloc_sym("br_result",1);
      }

      str+="\tbr "+reduce_left_sym+", %then_"+if_num+", %else_"+if_num+"\n";
      str+="%then_"+if_num+":\n";
      str+="\tstore 1, @br_result_1\n";
      str+="\tjump %end_"+if_num+"\n";

      str+="%else_"+if_num+":\n";

      if(!right_ret_exec){
        right_ret = right_ast->Dump(str);
      }
      std::string reduce_right_sym = "%"+std::to_string(get_a_symb_num());
      str+= "\t"+reduce_right_sym + " = ne "+right_ret + ", 0\n";
      str+="\tstore "+reduce_right_sym+", @br_result_1\n";
      str+="\tjump %end_"+if_num+"\n";

      str+="%end_"+if_num+":\n";
      std::string t_symb="%"+std::to_string(get_a_symb_num());

      str+="\t"+t_symb+" = load @br_result_1\n";

      return t_symb;
    }
    else assert(false);
  }
};

class LAndExpAST : public BaseExpAST {
 public:
  LAndExpAST(int _exp_num):BaseExpAST(_exp_num){}

  std::string Dump(std::string &str) const override {
    if(exp_num==1){
      return left_ast->Dump(str);
    }
    else if(exp_num==2){
      std::string left_ret = left_ast->Dump(str);
      std::string right_ret;
      bool right_ret_exec=false;

      if(isConst(left_ret)){
        if(left_ret!="0"){
          right_ret = right_ast->Dump(str);
          right_ret_exec=true;
          if(isConst(right_ret)) {
            if(right_ret!="0")return "1";
            else return "0";
          }
        }
        else return "0";
      }

      // 短路
      int current_if_num=if_def_count++;
      std::string if_num=std::to_string(current_if_num);

      // 变量result，用于存储短路结果
      if(!global_symbol_table.sym_is_alloc("br_result",1)){
        str+="\t@br_result_1 = alloc i32\n";
        global_symbol_table.record_alloc_sym("br_result",1);
      }

      std::string reduce_left_sym = "%"+std::to_string(get_a_symb_num());
      str+= "\t"+reduce_left_sym + " = ne "+left_ret + ", 0\n";

      str+="\tbr "+reduce_left_sym+", %then_"+if_num+", %else_"+if_num+"\n";

      str+="%then_"+if_num+":\n";

      if(!right_ret_exec)right_ret = right_ast->Dump(str);
      std::string reduce_right_sym = "%"+std::to_string(get_a_symb_num());
      str+= "\t"+reduce_right_sym + " = ne "+right_ret + ", 0\n";
      str+="\tstore "+reduce_right_sym+", @br_result_1\n";
      str+="\tjump %end_"+if_num+"\n";

      str+="%else_"+if_num+":\n";
      str+="\tstore 0, @br_result_1\n";
      str+="\tjump %end_"+if_num+"\n";

      str+="%end_"+if_num+":\n";
      std::string t_symb="%"+std::to_string(get_a_symb_num());
      str+="\t"+t_symb+" = load @br_result_1\n";

      return t_symb;
    }
    else assert(false);
  }
};

class ExpAST : public BaseExpAST {
 public:
  ExpAST(int _exp_num):BaseExpAST(_exp_num){}

  std::string Dump(std::string &str) const override {
      return left_ast->Dump(str);
  }
};


// 常量部分 

class ConstExpAST : public BaseExpAST {
public:
  ConstExpAST():BaseExpAST(1){}

  std::string Dump(std::string &str) const override {
      return left_ast->Dump(str);
  }
};

class ConstDefAST : public BaseExpAST {
public:
  ConstDefAST(int _num):BaseExpAST(_num){}

  std::vector<std::unique_ptr<BaseAST>> dim_exps;

  std::string Dump(std::string &str) const override {
    switch (exp_num)
    {
    case 0:
    {
      return left_ast->Dump(str);
    }
    case 1:
    {
      for(int i=0;i<dim_exps.size();i++){
        std::string dim_value=dim_exps[i]->Dump(str);
        arr_dim_sizes.push_back(dim_value);
      }
      std::string right_exp_ret=left_ast->Dump(str);
      gb_arr_elems.push_back(right_exp_ret);
      return right_exp_ret;
    }
    default:
      assert(false);
    }
  }
};

class ConstDeclAST : public BaseExpAST {
public:
  std::vector<std::unique_ptr<BaseExpAST>> cons;
  ConstDeclAST():BaseExpAST(0){}

  std::string Dump(std::string &str) const override {
    // 全局变量不需要描述
    if(block_deep==0){
      for(int i=0;i<cons.size();i++){
        std::string fake_str;
        std::string ret_result=cons[i]->Dump(fake_str);

        if(cons[i]->isArr){
          std::string alloc_s="[i32, "+arr_dim_sizes[arr_dim_sizes.size()-1]+"]";
          for(int i=arr_dim_sizes.size()-2;i>=0;i--){
            alloc_s="["+alloc_s+", "+arr_dim_sizes[i]+"]";
          }
          str+="global @"+cons[i]->ident+"_0 = alloc "+alloc_s;         
          if(gb_arr_elems.size()>0){
                str+=", "+gb_arr_elems[0];
            }
          str+="\n";

          // 数组头置位标记
          global_symbol_table.insert_new_var(cons[i]->ident, block_deep);
          for(int j=0;j<arr_content_elems.size();j++){
            global_symbol_table.insert_new_var(cons[i]->ident+"$_"+std::to_string(j), block_deep);
          }

          // 存入数组维数信息
          global_symbol_table.insert_arr_dim_info(global_symbol_table.var_get_ref(cons[i]->ident,block_deep),arr_dim_sizes,block_deep);
          arr_content_elems.clear();
        }
        else{
          int value=std::stoi(ret_result);
          global_symbol_table.insert_new_const(cons[i]->ident,value, block_deep);
        }
      }
    }
    else{
      for(int i=0;i<cons.size();i++){
        arr_dim_sizes.clear();
        std::string ret_result=cons[i]->Dump(str);
        if(cons[i]->isArr){
          if(arr_dim_sizes.size()==0)assert(false);
          std::string alloc_s="[i32, "+arr_dim_sizes[arr_dim_sizes.size()-1]+"]";
          for(int i=arr_dim_sizes.size()-2;i>=0;i--){
            alloc_s="["+alloc_s+", "+arr_dim_sizes[i]+"]";
          }

          // 数组头置位标记
          global_symbol_table.insert_new_var(cons[i]->ident, block_deep);
          str+="\t"+global_symbol_table.var_get_ref(cons[i]->ident, block_deep)+"= alloc "+alloc_s+"\n";
          str+="\tstore "+ret_result+", "+global_symbol_table.var_get_ref(cons[i]->ident,block_deep)+"\n";
        

          for(int j=0;j<arr_content_elems.size();j++){
            global_symbol_table.insert_new_var(cons[i]->ident+"$_"+std::to_string(j), block_deep);
          }

          // 存入数组维数信息
          global_symbol_table.insert_arr_dim_info(global_symbol_table.var_get_ref(cons[i]->ident,block_deep),arr_dim_sizes,block_deep);

          arr_content_elems.clear();
        }
        else{
          int value=std::stoi(ret_result);
          global_symbol_table.insert_new_const(cons[i]->ident,value, block_deep);
        }
      }
    }

    return "XXXX";
  }
};


class InitValAST : public BaseExpAST {
public:
  InitValAST(int _num):BaseExpAST(_num){}

  std::vector<std::unique_ptr<BaseAST>> vals;

  std::string Dump(std::string &str) const override {
    switch (exp_num)
    {
    case 0:
    {
      std::string exp_value=left_ast->Dump(str);
      return exp_value;
    }
    case 1:
    {
      current_arr_deep++;
      // 第一层为1
      int here_arr_deep=current_arr_deep;
      int rightest_dim=std::stoi(arr_dim_sizes[arr_dim_sizes.size()-1]);
      int deeper_total_num=1;
      for(int i=here_arr_deep-1;i<arr_dim_sizes.size();i++){
        deeper_total_num*=std::stoi(arr_dim_sizes[i]);
      }

      std::string temp_str;
      int current_arr_fill_offset=arr_fill_offset;

      int parsed_count=0;
      while(parsed_count<vals.size()){
        while(parsed_count<vals.size() && !vals[parsed_count]->isArr){
          std::string exp_value=vals[parsed_count]->Dump(temp_str);
          arr_content_elems.push_back(exp_value);
          parsed_count++;
        }

        if(parsed_count>=vals.size())break;

        arr_fill_offset=arr_content_elems.size();
        vals[parsed_count]->Dump(temp_str);

        if(arr_content_elems.size()%rightest_dim!=0){
          int bool_supply_num=rightest_dim-(arr_content_elems.size()%rightest_dim);
          for(int j=0;j<bool_supply_num;j++){
            arr_content_elems.push_back("0");
          }
        }

        parsed_count++;
      }


      arr_fill_offset=current_arr_fill_offset;

      if(here_arr_deep>1){
        // 上述算法正确实现时，不应该出现的
        if(arr_content_elems.size()>arr_fill_offset+rightest_dim)assert(false);
        for(int i=arr_content_elems.size();i<arr_fill_offset+rightest_dim;i++){
          arr_content_elems.push_back("0");
        }
      }
      else{
        if(arr_content_elems.size()>arr_fill_offset+deeper_total_num)assert(false);
        for(int i=arr_content_elems.size();i<arr_fill_offset+deeper_total_num;i++){
          arr_content_elems.push_back("0");
        }
      }

      current_arr_deep--;

      if(here_arr_deep>1)return "XXXX";
      // 数组最外层，做相应的字符串修饰步骤 {{...}...}

      std::vector<std::string> to_merged=arr_content_elems;
      for(int i=arr_dim_sizes.size()-1;i>=0;i--){
        int dim_size=std::stoi(arr_dim_sizes[i]);

        int count=0;
        std::vector<std::string> finished_merged;
        while(count<to_merged.size()){
          std::string merged_item="{";
          // 如果前面算法没有写错的话，这里是恰好个数对齐的
          for(int j=0;j<dim_size;j++){
            merged_item+=to_merged[count];
            if(j!=dim_size-1){
              merged_item+=", ";
            }
            count++;
          }
          merged_item+="}";
          finished_merged.push_back(merged_item);
        }
    
        to_merged=finished_merged;
      }
      arr_content_elems.clear();
      return to_merged[0];
    }
    default:
      assert(false);
    }
  }
};

class ConstInitValAST : public BaseExpAST {
 public:
  ConstInitValAST(int _num):BaseExpAST(_num){}

  std::vector<std::unique_ptr<BaseAST>> consts;

  std::string Dump(std::string &str) const override {
    switch (exp_num)
    {
    case 0:
    {
      std::string const_value=left_ast->Dump(str);
      return const_value;
    }
    case 1:
    {
      current_arr_deep++;
      // 第一层为1
      int here_arr_deep=current_arr_deep;
      int rightest_dim=std::stoi(arr_dim_sizes[arr_dim_sizes.size()-1]);
      int deeper_total_num=1;
      for(int i=here_arr_deep-1;i<arr_dim_sizes.size();i++){
        deeper_total_num*=std::stoi(arr_dim_sizes[i]);
      }

      std::string temp_str;
      int current_arr_fill_offset=arr_fill_offset;

      int parsed_count=0;
      while(parsed_count<consts.size()){
        while(parsed_count<consts.size() && !consts[parsed_count]->isArr){
          std::string exp_value=consts[parsed_count]->Dump(temp_str);
          arr_content_elems.push_back(exp_value);
          parsed_count++;
        }

        if(parsed_count>=consts.size())break;

        arr_fill_offset=arr_content_elems.size();
        consts[parsed_count]->Dump(temp_str);

        if(arr_content_elems.size()%rightest_dim!=0){
          int bool_supply_num=rightest_dim-(arr_content_elems.size()%rightest_dim);
          for(int j=0;j<bool_supply_num;j++){
            arr_content_elems.push_back("0");
          }
        }

        parsed_count++;
      }


      arr_fill_offset=current_arr_fill_offset;

      if(here_arr_deep>1){
        // 上述算法正确实现时，不应该出现的
        if(arr_content_elems.size()>arr_fill_offset+rightest_dim)assert(false);
        for(int i=arr_content_elems.size();i<arr_fill_offset+rightest_dim;i++){
          arr_content_elems.push_back("0");
        }
      }
      else{
        if(arr_content_elems.size()>arr_fill_offset+deeper_total_num)assert(false);
        for(int i=arr_content_elems.size();i<arr_fill_offset+deeper_total_num;i++){
          arr_content_elems.push_back("0");
        }
      }

      current_arr_deep--;

      if(here_arr_deep>1)return "XXXX";
      // 数组最外层，做相应的字符串修饰步骤 {{...}...}

      std::vector<std::string> to_merged=arr_content_elems;
      for(int i=arr_dim_sizes.size()-1;i>=0;i--){
        int dim_size=std::stoi(arr_dim_sizes[i]);

        int count=0;
        std::vector<std::string> finished_merged;
        while(count<to_merged.size()){
          std::string merged_item="{";
          // 如果前面算法没有写错的话，这里是恰好个数对齐的
          for(int j=0;j<dim_size;j++){
            merged_item+=to_merged[count];
            if(j!=dim_size-1){
              merged_item+=", ";
            }
            count++;
          }
          merged_item+="}";
          finished_merged.push_back(merged_item);
        }
    
        to_merged=finished_merged;
      }

      // arr_content_elems.clear(); 交给ConstDecl清理
      return to_merged[0];
    }
    default:
      assert(false);
    }
  }
};

class DeclAST : public BaseAST {
public:
  std::unique_ptr<BaseAST> next;
  std::string Dump(std::string &str) const override {
      return next->Dump(str);
  }
};

class VarDefAST : public BaseExpAST {
public:
  VarDefAST(int _num):BaseExpAST(_num){}

  std::vector<std::unique_ptr<BaseAST>> dims;

  std::string Dump(std::string &str) const override {
    switch (exp_num)
    {
    case 0:
    {
      return "0";
    }
    case 1:
    {
      std::string left_ret = left_ast->Dump(str);
      if(block_deep==0){
        if(!isConst(left_ret))assert(false);
        global_symbol_table.insert_new_const(ident,std::stoi(left_ret),block_deep);
      }
      else {
        str+="\tstore "+left_ret+", "+global_symbol_table.var_get_ref(ident,block_deep)+"\n";
      }
      return left_ret;
    }
    case 2:
    {
      for(int i=0;i<dims.size();i++){
        arr_dim_sizes.push_back(dims[i]->Dump(str));
      }

      int i_dim=std::stoi(arr_dim_sizes[arr_dim_sizes.size()-1]);
      std::string arr_value="{";
      for(int j=0;j<i_dim;j++){
        arr_value+="0";
        if(j!=i_dim-1){
          arr_value+=", ";
        }
      }
      arr_value+="}";

      std::string final_value=arr_value;      
      for(int i=arr_dim_sizes.size()-2;i>=0;i--){
        int dim=std::stoi(arr_dim_sizes[i]);
        std::string next_value="{";
        for(int j=0;j<dim;j++){
          next_value+=final_value;
          if(j!=dim-1){
            next_value+=", ";
          }
        }
        next_value+="}";
        final_value=next_value;
      }

      gb_arr_elems.push_back(final_value);
      str+="\tstore "+final_value+", "+global_symbol_table.var_get_ref(ident,block_deep)+"\n";

      return "XXXXXXX";
    }
    case 3:
    {
      for(int i=0;i<dims.size();i++){
        arr_dim_sizes.push_back(dims[i]->Dump(str));
      }

      std::string initVal = left_ast->Dump(str);

      gb_arr_elems.push_back(initVal);
      str+="\tstore "+initVal+", "+global_symbol_table.var_get_ref(ident,block_deep)+"\n";

      return "XXXXXXX";
    }
    default:
      assert(false);
    }
  }
};

class VarDeclAST : public BaseExpAST {
public:
  std::vector<std::unique_ptr<BaseAST>> vars;
  VarDeclAST():BaseExpAST(0){}

  std::string Dump(std::string &str) const override {
    for(int i=0;i<vars.size();i++){
      if(block_deep==0){
        // 存入变量符号表
        global_symbol_table.insert_new_var(vars[i]->ident,block_deep);
        std::vector<std::string> temp_gb_arr_elems=gb_arr_elems;
        std::vector<std::string> temp_arr_dim_sizes=arr_dim_sizes;
        gb_arr_elems.clear();
        arr_dim_sizes.clear();
        std::string fake_str;
        std::string s_value=vars[i]->Dump(fake_str);

        if(vars[i]->isArr){
          std::string alloc_s="[i32, "+arr_dim_sizes[arr_dim_sizes.size()-1]+"]";
          for(int i=arr_dim_sizes.size()-2;i>=0;i--){
            alloc_s="["+alloc_s+", "+arr_dim_sizes[i]+"]";
          }

          str+="global @"+vars[i]->ident+"_0 = alloc "+alloc_s;         
          if(gb_arr_elems.size()>0){
                str+=", "+gb_arr_elems[0];
            }
          str+="\n";

          // 存入数组维数信息
          global_symbol_table.insert_arr_dim_info(global_symbol_table.var_get_ref(vars[i]->ident,block_deep),arr_dim_sizes,block_deep);
        }
        else{
          str+="global @"+vars[i]->ident+"_0 = alloc i32, "+s_value+"\n";
        }

        gb_arr_elems=temp_gb_arr_elems;
        arr_dim_sizes=temp_arr_dim_sizes;
      }
      else{
        bool alloc_need=false;
        if(!global_symbol_table.sym_is_alloc(vars[i]->ident,block_deep)){
          alloc_need=true;
          // 存入变量符号表
          global_symbol_table.insert_new_var(vars[i]->ident,block_deep);
          global_symbol_table.record_alloc_sym(vars[i]->ident,block_deep);  
        }

        std::vector<std::string> temp_gb_arr_elems=gb_arr_elems;
        std::vector<std::string> temp_arr_dim_sizes=arr_dim_sizes;
        gb_arr_elems.clear();
        arr_dim_sizes.clear();

        std::string delay_str="";
        std::string arr_size=vars[i]->Dump(delay_str);

        if(alloc_need){
          if(vars[i]->isArr){
            if(arr_dim_sizes.size()==0)assert(false);
            std::string alloc_s="[i32, "+arr_dim_sizes[arr_dim_sizes.size()-1]+"]";
            for(int i=arr_dim_sizes.size()-2;i>=0;i--){
              alloc_s="["+alloc_s+", "+arr_dim_sizes[i]+"]";
            }
            str+="\t"+global_symbol_table.var_get_ref(vars[i]->ident,block_deep)+"= alloc "+alloc_s+"\n";
          
            // 存入数组维数信息
            global_symbol_table.insert_arr_dim_info(global_symbol_table.var_get_ref(vars[i]->ident,block_deep),arr_dim_sizes,block_deep);
          }
          else{
            str+="\t"+global_symbol_table.var_get_ref(vars[i]->ident,block_deep)+"= alloc i32\n";
          } 
        }

        str+=delay_str;

        gb_arr_elems=temp_gb_arr_elems;
        arr_dim_sizes=temp_arr_dim_sizes;

      }
    }
    return "";
  }
};

class BlockItemAST : public BaseAST {
public:
  std::unique_ptr<BaseAST> next;
  std::string Dump(std::string &str) const override {
    std::string _t=next->Dump(str);
    return _t;
  }
};

class IfElseStmtAST : public BaseExpAST {
public:
  IfElseStmtAST(int _num):BaseExpAST(_num){}
  std::string Dump(std::string &str) const override {
    std::string condition_result=left_ast->Dump(str);

    int current_if_num=if_def_count++;    std::string if_num=std::to_string(current_if_num);
    str+="\tbr "+condition_result+", %then_"+if_num+", %else_"+if_num+"\n";

    str+="%then_"+if_num+":\n";

    bLastIsReturn=bLastIsBreak=bLastIsContinue=false;

    current_block_num++;
    std::string if_ret=right_ast->Dump(str);
    if(!bLastIsReturn && !bLastIsBreak && !bLastIsContinue)
      str+="\tjump %end_"+if_num+"\n";
  
    str+="%else_"+if_num+":\n";

    bLastIsReturn=bLastIsBreak=bLastIsContinue=false;
    if(exp_num==3){
      current_block_num++;
      std::string else_ret=more_ast0->Dump(str);
    }

    if(!bLastIsReturn  && !bLastIsBreak && !bLastIsContinue)
      str+="\tjump %end_"+if_num+"\n";

    str+="%end_"+if_num+":\n";
    bLastIsReturn=bLastIsBreak=bLastIsContinue=false;


    return if_num;
  }
};

class WhileStmtAST : public BaseExpAST {
public:
  WhileStmtAST(int _num):BaseExpAST(_num){}
  std::string Dump(std::string &str) const override {
    int current_while_def_count=while_def_count++;
    while_num_stack.push(current_while_def_count);
    std::string s_current_while_def_count=std::to_string(current_while_def_count);
    str += "\tjump %while_entry_"+s_current_while_def_count+"\n";
    str += "%while_entry_"+s_current_while_def_count+":\n";
    std::string condition_result = left_ast->Dump(str);
    str += "\tbr "+condition_result+", %while_body_"+s_current_while_def_count+", %end_while_"+s_current_while_def_count+"\n";

    str+="%while_body_"+ s_current_while_def_count +":\n";
    bLastIsReturn=bLastIsBreak=bLastIsContinue=false;
    right_ast->Dump(str);
    if(!bLastIsReturn && !bLastIsBreak && !bLastIsContinue)
      str+="\tjump %while_entry_"+s_current_while_def_count+"\n";

    str+="%end_while_"+s_current_while_def_count+":\n";
    bLastIsReturn=bLastIsBreak=bLastIsContinue=false;
    while_num_stack.pop();
    return "";
  }
};

class BreakStmtAST : public BaseAST {
public:
  std::string Dump(std::string &str) const override {
    int last_while_def_count=while_num_stack.top();
    std::string s_last_while_def_count=std::to_string(last_while_def_count);
    if(while_def_count<0)assert(false);

    str+="\tjump %end_while_"+s_last_while_def_count+"\n";
    return "";
  }
};

class ContinueStmtAST : public BaseAST {
public:
  std::string Dump(std::string &str) const override {
    int last_while_def_count=while_num_stack.top();
    std::string s_last_while_def_count=std::to_string(last_while_def_count);
    if(while_def_count<0)assert(false);

    str+="\tjump %while_entry_"+s_last_while_def_count+"\n";
    return "";
  }
};


class BlockItemMoreAST : public LinkNodeAST {
};

class ExpMoreAST : public LinkNodeAST {
};

class FuncFParamMoreAST {
public:
  virtual ~FuncFParamMoreAST() = default;
  std::unique_ptr<FuncFParamAST> current;
  std::unique_ptr<FuncFParamMoreAST> next;
};

class ConstDefMoreAST : public ExpLinkNodeAST {
};

class VarDefMoreAST : public LinkNodeAST {
};

class ConstExpMoreAST : public LinkNodeAST {
};

class ArrDimMoreAST: public LinkNodeAST {
};

class ArrayIndexMoreAST: public LinkNodeAST {
};

class ConstInitValMoreAST: public LinkNodeAST {
};

class InitValMoreAST: public LinkNodeAST {
};
